<template>
  <div class="grid-rq" :ref="this.refId+'text'">
    <div class="grid-title" v-if="gridTitle != null">
      <span>{{gridTitle}}</span>
    </div>
    <el-table v-loading="gridLoading" :data="gridData" :height="gridHeight" :ref="refId" border :highlight-current-row="false" @selection-change="handleSelectionChange"
      @current-change="handleCurrentChange" @sort-change="handleSortChange" @row-click="rowclick" :header-row-class-name="headerRowClassName" :cell-class-name="cellClassName"
      :tree-props="treeProps" :row-key="rowKey" stripe>
      <div v-if="indexNo">
        <el-table-column type="index" label="序号" :fixed="true" align="center" width="60">
        </el-table-column>
      </div>
      <div v-if="createPointNumber">
        <el-table-column type="index" align="center" :fixed="true" width="1">
          <template slot-scope="scope">
            <template>
              <div :id="'point'+scope.row[pointFiled]" class="point-item">
              </div>
            </template>
          </template>
        </el-table-column>
      </div>
      <div v-if="multi">
        <el-table-column v-if="multi" header-align="center" :fixed="true" align="center" type="selection" width="50"></el-table-column>
      </div>
      <div v-for="(cols, index) in columns" :key="index">
        <el-table-column v-if="cols.template" :header-align="cols.headerAlign" :align="cols.align" :formatter="cols.formatter" :sortable="cols.sortable" :prop="cols.prop"
          :type="cols.order" :label="cols.label" :fixed="cols.fixed || false" :width="cols.width" :min-width="cols.minWidth" :row-style="{height:'38px'}"
          :header-row-style="{height:'38px'}" :cell-style="{padding:'2px'}" :header-cell-style="{padding:'2px'}">
          <template slot-scope="scope">
            <template v-if="cols.template == 'tree'">
              <div :style="{marginLeft:getLeft(scope.row['level'])}">
                <i class="el-icon-caret-bottom" style="color:red;" @click="unExpand(scope.row,scope.row[cols.prop])" v-if="scope.row['expand']"></i>
                <i class="el-icon-caret-right" style="color:green;" @click="expand(scope.row,scope.row[cols.prop])" v-if="!scope.row['expand']"></i>
              </div>
            </template>
            <template v-if="cols.template == 'img'">
              <div class="img-div">
                <img class="img-bd" v-if="isPro" :src="cols.prefix + scope.row[cols.prop]" width="28" height="28" />
                <div class="img-text">{{scope.row[cols.templateProp]}}</div>
              </div>
            </template>
            <template v-if="cols.template == 'switch'">
              <el-switch v-model="scope.row[cols.prop]" active-color="#13ce66" inactive-color="#ff4949" @change="switchChange(scope.row,scope.row[cols.prop])"></el-switch>
            </template>
            <template v-if="cols.template == 'icon'">
              <i :class="scope.row[cols.prop]"></i>
            </template>
            <template v-if="cols.template == 'cell'">
              <div class="cell-text">{{scope.row[cols.prop]}}</div>
            </template>
            <template v-if="cols.template == 'number'">
              <div class="cell-text">{{scope.row[cols.prop] | twoNumber}}</div>
            </template> <template v-if="cols.template == 'op'">
              <span class="opBtn" href="#" v-for="(op,index) in cols.opList" :key="index" @click="opClick(scope.row,op.clickName,op.confirm)" v-if="permissions[op.auth]"
                v-show="opBtnShow(scope.row[op.prop],scope.row[op.valueProp],op.showValue)">{{op.name}}</span>
            </template>
            <template v-if="cols.template == 'sortStatus'">
              <div v-if="scope.row[cols.prop] >0" style="color:red;">{{scope.row[cols.prop] }}<i class="rayicon iconfont icon-jiantou-copy"></i></div>
              <div v-if="scope.row[cols.prop] <0" style="color:green;">{{scope.row[cols.prop] }}<i class="rayicon iconfont icon-jiantou"></i></div>
              <div v-if="scope.row[cols.prop] ==0">-</div>
            </template>
            <template v-if="cols.template == 'sortColor'">
              <div v-if="scope.row[cols.prop] >0" style="color:red;">+{{scope.row[cols.prop]*100 | oneNumber }}%</div>
              <div v-if="scope.row[cols.prop] <0" style="color:green;">{{scope.row[cols.prop]*100 | oneNumber }}%</div>
              <div v-if="scope.row[cols.prop] ==0">-</div>
            </template>
            <template v-if="cols.template == 'bgColor'">
              <div :style="{color:bgColor(cols.bgColor,scope.row[cols.prop],scope.row)}">{{bgColorValue(cols.formatter,scope.row[cols.prop],scope.row)}}</div>
            </template>
            <template v-else-if="cols.template == 'edit'">
              <div class="edit-div">
                <el-input :type="scope.row.type ? scope.row.type : 'text'" v-if="scope.row.editable" @blur="doEditAfter(scope.$index,scope.row,cols.prop)"
                  v-model="scope.row[cols.prop]"></el-input>
                <div class="edit-value" @dblclick="editClick(scope.$index,scope.row)" v-if="!scope.row.editable">{{scope.row[cols.prop]}}</div>
              </div>
            </template>
          </template>
        </el-table-column>
        <el-table-column v-if="!cols.template" :header-align="cols.headerAlign" :align="cols.align" :formatter="cols.formatter" :sortable="cols.sortable" :prop="cols.prop"
          :type="cols.order" :label="cols.label" :fixed="cols.fixed" :width="cols.width" :min-width="cols.minWidth">
        </el-table-column>
      </div>

    </el-table>
    <div class="grid-pagination" v-if="pagination">
      <el-pagination class="grid-pagination-content" @size-change="handleSizeChange" @current-change="handlePageChange" :current-page="page.currentPage" :page-sizes="pageSizes"
        :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="page.totalCount">
      </el-pagination>
    </div>
    <!-- 锚点 跳转 -->
    <div class="grid-point" v-if="showPoint">
      <div class="grid-point-item" v-for="(page, index) in pointEntity.size" :key="index" @click="pointClick(page)">
        {{(page-1)*pointEntity.pageSize+1}}-
        {{page*pointEntity.pageSize}}
      </div>
    </div>
  </div>
</template>
<script>
import request from "@/router/axios";
import { Message, MessageBox } from "element-ui";

export default {
  name: "treeGrid",
  data () {
    return {
      isPro: true,
      gridLoading: false,
      editableStatus: [],
      gridData: [],
      gridHeight: null,
      titleHeight: 40,
      bottomHeight: 40,
      currentRows: null,
      currentRow: null,
      pointEntity: {
        size: 0,
        pageSize: 50,
        loadingPage: 1
      },
      query: {
        text: null,
        entity: null
      },
      page: {
        pageSize: 0,
        currentPage: 1,
        totalCount: 0,
        orderBy: ""
      }
    };
  },
  filters: {
    oneNumber: function (value) {
      value = Number(value);
      return value.toFixed(1);
    },
    twoNumber: function (value) {
      value = Number(value);
      return value.toFixed(2);
    }
  },
  props: {
    url: {
      type: String,
      default: function () {
        return null;
      }
    },
    diffHeight: {
      type: String,
      default: function () {
        return "0";
      }
    },
    headerRowClassName: {
      type: String,
      default: function () {
        return null;
      }
    },
    cellClassName: {
      type: String,
      default: function () {
        return null;
      }
    },
    rowKey: {
      type: String,
      default: function () {
        return "id";
      }
    },
    pointFiled: {
      type: String,
      default: function () {
        return "indexSort";
      }
    },
    resultType: {
      type: String,
      default: function () {
        return "Object";
      }
    },
    gridTitle: {
      type: String,
      default: function () {
        return null;
      }
    },
    orderField: {
      type: String,
      default: function () {
        return null;
      }
    },
    orderType: {
      type: String,
      default: function () {
        return " desc ";
      }
    },
    treeProps: {
      type: Object,
      default: function () {
        return { children: 'children', hasChildren: 'hasChild' };
      }
    },
    method: {
      type: String,
      default: function () {
        return "post";
      }
    },
    refId: {
      type: String,
      default: function () {
        return "mainGrid";
      }
    },
    height: {
      type: String,
      default: function () {
        return null;
      }
    },
    multi: {
      type: Boolean,
      default: function () {
        return false;
      }
    },
    expandTree: {
      type: Boolean,
      default: function () {
        return false;
      }
    },
    showPoint: {
      type: Boolean,
      default: function () {
        return false;
      }
    },
    createPointNumber: {
      type: Boolean,
      default: function () {
        return false;
      }
    },
    permissions: {
      type: Object,
      default: function () {
        return {};
      }
    },
    indexNo: {
      type: Boolean,
      default: function () {
        return true;
      }
    },
    pageSize: {
      type: Number,
      default: function () {
        return 10;
      }
    },
    pageSizes: {
      type: Array,
      default: function () {
        return [10, 20, 50, 100];
      }
    },
    columns: {
      type: Array
    },
    rowClickName: {
      type: String
    },
    queryText: {
      type: String
    },
    queryEntity: {
      type: Object
    },
    pagination: {
      type: Boolean,
      default: function () {
        return false;
      }
    },
    loading: {
      type: Boolean,
      default: function () {
        return true;
      }
    }
  },
  created () {
    this.resetDiffHeight(this.diffHeight);
    this.page.pageSize = this.pageSize;
    // 获取参数
    this.query.text = this.queryText;
    this.query.entity = this.queryEntity;
    // 设置排序字段
    if (this.orderField) {
      this.page.orderBy = this.orderField + " " + this.orderType;
    }
  },
  mounted () {
    if (this.loading) {
      this.gridQuery();
    }
  },
  methods: {
    gridQuery () {
      this.gridLoading = true;
      const data = this.createQueryData();
      this.handlePage(data).then(result => {
        this.gridLoading = false;
        console.log(result)
        if (this.pagination) {
          this.gridData = result.records;
          this.page.currentPage = result.page;
          this.page.pageSize = result.pageSize;
          this.page.totalCount = result.total;
          this.initPointToatl(result.total);
        } else {
          this.gridData = result;
        }
      });
    },
    initPointToatl (total) {
      this.$emit("totalCallback", total);
      if (total % this.pointEntity.pageSize === 0) {
        this.pointEntity.size = total / this.pointEntity.pageSize;
      } else {
        this.pointEntity.size = parseInt(total / this.pointEntity.pageSize) + 1;
      }
      this.pointEntity.loadingPage = 1;
    },
    handleSortChange (col) {
      let orderType = "";
      if (col.order === "ascending") {
        orderType = "  asc";
      } else {
        orderType = "  desc";
      }
      if (!col.column || !col.column.type) return;
      this.page.orderBy = col.column.type + orderType;
      this.gridQuery();
    },
    handleSizeChange (val) {
      this.page.pageSize = val;
      this.gridQuery();
    },
    handlePageChange (val) {
      this.page.currentPage = val;
      this.gridQuery();
    },
    handleCurrentChange (row) {
      this.currentRow = row;
      if (this.multi) {
        this.$refs[this.refId].toggleRowSelection(row);
      }
      this.$emit("change", row);
    },
    handleSelectionChange (rows) {
      this.currentRows = rows;
      this.$emit("change", rows);
    },
    rowclick (row, event, col) {
      if (this.rowClickName) {
        this.$emit(this.rowClickName, row, event, col);
      }
    },
    getCurrentRow () {
      if (this.multi) {
        if (this.currentRows && this.currentRows.length == 1) {
          return this.currentRows[0]
        } else {
          return null;
        }
      } else {
        return this.currentRow
      }
    },
    getCurrentRows () {
      return this.currentRows;
    },
    getSelectOne () {
      if (this.currentRows.length == 1) {
        return this.currentRows[0]
      } else {
        MessageBox.alert("请选择一行数据");
        return null;
      }
    },
    getData () {
      return this.gridData;
    },
    initData (data) {
      this.gridData = data
    },
    addRow (rowData) {
      this.gridData.push(rowData);
      this.page.totalCount = this.page.totalCount + 1;
    },
    setOrderField (orderField, orderType) {
      this.page.orderBy = orderField + " " + orderType;
    },
    setPageSize (size) {
      this.page.pageSize = size;
      this.gridQuery();
    },
    resetDiffHeight (diffHeight) {
      if (this.height === "auto") {
        this.gridHeight =
          window.innerHeight - diffHeight - this.titleHeight - 5;
        if (this.pagination) {
          this.gridHeight = this.gridHeight - this.bottomHeight;
        }
      } else if (this.height.indexOf(":") === 0) {
        const value = parseFloat("0." + this.height.substring(1));
        this.gridHeight =
          (window.innerHeight - diffHeight) * value - this.titleHeight - 5;
        if (this.pagination) {
          this.gridHeight = this.gridHeight - this.bottomHeight;
        }
      }
    },
    deleteRow (rowData) {
      const index = this.gridData.indexOf(rowData);
      if (index >= 0) {
        this.gridData.splice(index, 1);
        this.page.totalCount = this.page.totalCount - 1;
      }
    },
    createQueryData () {
      if (this.method == "post") {
        let queryData = {
          page: {
            current: this.page.currentPage,
            size: this.page.pageSize,
            orderBy: this.page.orderBy
          },
          query: this.query.text,
          entity: this.query.entity
        }
        if (!this.pagination) {
          queryData = this.query.entity
        }
        return queryData;
      } else {
        this.query.entity.query = this.query.text;
        return this.query.entity;
      }
    },
    reload () {
      this.gridQuery();
    },
    doQuery (query, entity) {
      this.query.text = query;
      this.query.entity = entity || this.queryEntity;
      this.gridQuery();
    },
    editClick (index, row) {
      this.$set(row, "editable", true);
      this.$emit("beforeEdit", row);
    },
    doEditAfter (index, row, prop) {
      this.$set(row, "editable", false);
      this.$emit("afterEdit", row, prop);
    },
    changeEditType (row, type = false) {
      this.$set(row, "editable", type);
    },
    opClick (row, name, confirm) {
      //this.$emit(name, row)
      let _this = this
      if (confirm) {
        this.$confirm("是否确认该操作, 是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(() => {
          this.showModal = true;
          try {
            this.$emit(name, row)
          } catch (e) {
            this.showModal = false
          }
          setTimeout(function () {
            _this.showModal = false
          }, 500)
        });
      } else {
        this.$emit(name, row)
      }
    },
    opBtnShow (value, valueProp, valueList) {
      if (valueList) {
        if (valueProp != null) {
          return valueList.indexOf(valueProp) >= 0
        } else {
          return valueList.indexOf(value) >= 0
        }
      }
      return true
    },
    bgColor (colors, key, row) {
      let color = "#000";
      if (colors && key) {
        color = colors[key];
      }
      return color;
    },
    bgColorValue (formatter, value, row) {
      if (formatter) {
        return formatter(row, null, value);
      }
      return value;
    },
    pointClick (page) {
      // 表示为加载到数据
      const jumpHeight = (page - 1) * this.pointEntity.pageSize * 49;
      this.$refs[this.refId + "text"].querySelector(
        ".el-table__body-wrapper"
      ).scrollTop = jumpHeight;
    },
    expand (row, data) {
      const _this = this;
      const index = this.gridData.indexOf(row);
      row.expand = true;
      data.forEach(function (r, i) {
        r.level = row.level ? row.level + 1 : 1;
        _this.gridData.splice(index + i + 1, 0, r);
      });
    },
    unExpand (row, data) {
      const _this = this;
      const index = this.gridData.indexOf(row);
      row.expand = false;
      data.forEach(function (r, i) {
        const cindex = _this.gridData.indexOf(r);
        _this.gridData.splice(cindex, 1);
      });
    },
    getLeft (level) {
      if (!level) level = 0;
      return level * 20 + "px";
    },
    switchChange (row, value) {
      this.$emit("switch", row, value);
    },
    handlePage (data) {
      if (this.method == "post") {
        return request({
          url: this.url,
          method: this.method,
          data
        });
      } else {
        return request({
          url: this.url,
          method: this.method,
          params: data
        });
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.grid-title {
  width: 100%;
  height: 40px;
  border: 1px solid rgb(235, 235, 235);
  span {
    height: 35px;
    padding-top: 12px;
    padding-left: 8px;
    float: left;
    font-family: '微软雅黑 Regular', '微软雅黑';
    font-size: 14px;
    color: #a2a2a2;
  }
}

.grid-pagination {
  width: 100%;
  height: 40px;
  border: 1px solid rgb(235, 235, 235);
  background-color: white;
  .grid-pagination-content {
    float: left;
    padding-top: 5px;
    padding-left: 15px;
  }
}
.img-div {
  text-align: left;
  margin-left: 15px;
  vertical-align: middle;
  .img-bd {
    float: left;
    margin-right: 3px;
  }
  .img-text {
    float: left;
    height: 28px;
    padding-top: 3px;
  }
}

.edit-div {
  text-align: left;
  margin-left: 15px;
  vertical-align: middle;
  .edit-value {
    width: 80%;
    text-align: center;
  }
}

.cell-text {
  font-family: 'Arial Negreta', 'Arial';
  font-weight: 700;
  font-style: normal;
  color: #4994f1;
}
.rayicon {
  vertical-align: middle;
}
.grid-point {
  position: absolute;
  bottom: 25px;
  right: -45px;
  width: 42px;
  .grid-point-item {
    text-align: center;
    vertical-align: middle;
    padding: 5px auto;
    width: 40px;
    height: 40px;
    border: 1px solid white;
    background-color: #4994f1;
    cursor: pointer;
    font-family: 'Arial Negreta', 'Arial';
    font-weight: 400;
    font-size: 12px;
    font-style: normal;
    color: white;
  }
}

.point-item {
  min-height: 30px;
}

.opBtn {
  cursor: pointer;
  font-weight: 500;
  font-style: normal;
  color: #4994f1;
  margin: 0px 5px;
}
</style>
